iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0

JobScheduler 與 WorkManager

intro

早期的 Android 背景任務排程主要依靠 AlarmManager。開發者會設定一個時間點讓 App 醒來執行某段程式,例如同步資料、發送通知等。但這種方式會造成以下問題:

  • ❌ 耗電量高:每個 App 都自行喚醒裝置,CPU 無法有效休眠。
  • ❌ 無法控制條件:無法指定「充電中再執行」或「需 Wi-Fi」等條件。
  • ❌ Doze 模式後失效:Android 6.0 起,Doze 模式會限制鬧鐘觸發頻率。
    為了改善這些問題,Android 5.0(API 21)引入了 JobScheduler,讓任務能在「滿足條件時由系統統一安排執行」。
    後來,為了讓開發者能跨版本、跨平台使用統一 API,Google 又在 Jetpack 推出 WorkManager,它會在底層根據系統版本自動選擇合適的排程方式(如 JobScheduler、AlarmManager、Firebase JobDispatcher)。

JobScheduler 架構概述

  1. JobScheduler 的定位
    JobScheduler 是 Android Framework 中的系統服務,名稱為 JobSchedulerService。它的職責是管理所有 App 註冊的「工作(Job)」任務,並根據系統狀態(如電源、網路、電池、閒置狀態等)決定何時觸發。

  2. 架構層級圖

[App 層]
   ↓
 JobScheduler API
   ↓
[Framework 層]
   JobSchedulerService
       ├─ JobStore (持久化工作)
       ├─ JobSchedulerService$JobHandler
       ├─ JobSchedulerService$JobSchedulerThread
   ↓
[System Server]
   AMS / PMS / PowerManager / BatteryStatsService
  1. 工作註冊與執行流程
  • App 呼叫:
val jobScheduler = context.getSystemService(JobScheduler::class.java)
val jobInfo = JobInfo.Builder(1, ComponentName(context, MyJobService::class.java))
    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
    .setRequiresCharging(true)
    .build()
jobScheduler.schedule(jobInfo)
  • Framework 端透過 Binder IPC 將 JobInfo 傳給 JobSchedulerService。
  • JobSchedulerService 儲存 Job 資訊於 JobStore.xml。
  • 當系統判斷條件符合(充電中 + Wi-Fi 可用),觸發對應的 JobService。
  • JobService 執行後回報結果給系統。
  1. 主要條件設定
    條件類型 方法 說明
    網路條件 setRequiredNetworkType() 僅在特定網路狀態下執行
    電源條件 setRequiresCharging() 僅在充電時執行
    閒置條件 setRequiresDeviceIdle() 僅在裝置閒置時執行
    週期性任務 setPeriodic() 定期執行(但間隔最短 15 分鐘)
    延遲執行 setMinimumLatency() 指定最早執行時間
    最長延遲 setOverrideDeadline() 超過時間後必定執行

  2. 內部 key components

  • JobStore:保存註冊的任務,支援持久化(重開機後仍可存在)。
  • JobSchedulerService$JobHandler:處理觸發邏輯。
  • JobServiceContext:執行 Job 的上下文管理。
  • JobConstraintsTracker:持續監控條件(網路/電源等)。

WorkManager 的設計理念與系統整合

  1. 為什麼需要 WorkManager?
    JobScheduler 僅在 API 21+ 可用,且不支援需要即時執行的簡單任務(例如低版本背景同步)。
    WorkManager 的誕生目的是:

“提供跨版本、可靠且可重啟的任務排程解決方案。”

  1. WorkManager 架構圖
[App 層]
  WorkManager API
      ↓
[AndroidX 層]
  WorkManager Runtime
      ├─ WorkDatabase (SQLite)
      ├─ WorkerWrapper
      ├─ TaskExecutor
      ↓
[排程層]
  ├─ JobScheduler (API 23+)
  ├─ AlarmManager + BroadcastReceiver (API 14–22)
  ├─ Firebase JobDispatcher (舊備援)
  1. 核心概念
    WorkManager 主要透過三個核心概念運作:

名稱 說明
Worker 實際執行任務的類別(如上傳檔案)
WorkRequest 定義任務內容與條件
WorkManager 任務調度與監控管理入口

  1. 使用範例
class UploadWorker(appContext: Context, workerParams: WorkerParameters)
    : Worker(appContext, workerParams) {
    override fun doWork(): Result {
        uploadDataToServer()
        return Result.success()
    }
}

// 建立任務
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.UNMETERED)
            .setRequiresCharging(true)
            .build()
    )
    .build()

// 提交任務
WorkManager.getInstance(context).enqueue(uploadWorkRequest)
  1. 系統自動對應層
    WorkManager 會根據系統版本自動選擇排程機制:

Android 版本 使用底層機制
API 23+ JobScheduler
API 14–22 AlarmManager + BroadcastReceiver
API 33+ JobScheduler + Battery Optimization Awareness
四、JobScheduler 與 WorkManager 的比較
項目 JobScheduler WorkManager
最低版本 API 21 API 14
條件支援 網路、電源、閒置等 網路、電源、儲存空間、自定條件
任務鏈接 ❌ 不支援 ✅ 支援工作鏈 (Chaining)
資料傳遞 Bundle Data (型別安全)
任務觀察 手動管理 LiveData / Coroutine Flow
任務持久化 可設定 自動持久化
適用場景 系統級背景任務 一般 App 背景同步
系統支援層 Framework Service Jetpack Library + System Service

JobScheduler 與系統支援整合

JobScheduler 並非獨立運作,它與多個系統服務協作:

  • PowerManagerService:監控裝置是否充電、閒置。
  • BatteryStatsService:回報工作對耗電的影響。
  • NetworkPolicyManagerService:監控網路狀態與使用政策。
  • AppStandbyController:控制長期未使用應用的任務延遲。
    這些服務共同確保 JobScheduler 能「在合適時機喚醒 App」,而不浪費電力。

WorkManager 與 Jetpack 生態整合

WorkManager 與 AndroidX 有深度整合:

  • Room:可在資料庫更新後觸發 Work
  • Hilt / Dagger:支援依賴注入的 Worker
  • Coroutine + Flow:支援 Kotlin 協程任務
  • Compose 與 Lifecycle:任務狀態可觀察

例如:

workManager.getWorkInfoByIdLiveData(workRequest.id)
    .observe(this) { workInfo ->
        if (workInfo.state == WorkInfo.State.SUCCEEDED) {
            Log.d("WorkManager", "Upload completed!")
        }
    }

節能政策下的運作差異

  1. Doze 模式
  • JobScheduler 會自動延遲任務,直到「Maintenance Window」開啟。
  • WorkManager 在底層沿用相同政策。
  1. App Standby
  • 長時間未啟動的 App 會被限制執行背景工作。
  • JobScheduler / WorkManager 皆受影響,但 WorkManager 會更平滑地延後執行。
  1. Battery Saver
  • 任務會被延後或暫停。
  • WorkManager 會自動保存工作狀態,待恢復後繼續執行。

  1. JobScheduler 架構
+----------------------+
|   JobScheduler API   |
+----------------------+
          |
          v
+----------------------+
| JobSchedulerService  |
|  + JobStore          |
|  + JobHandler        |
|  + ConstraintsTracker|
+----------------------+
          |
          v
+----------------------+
| System Services (Power, Net, Battery) |
+--------------------------------------+
  1. WorkManager 運作層級
+---------------------------+
| WorkManager API (App)     |
+---------------------------+
           |
           v
+---------------------------+
| WorkManager Runtime       |
|  - WorkDatabase           |
|  - Scheduler API          |
|  - WorkerWrapper          |
+---------------------------+
           |
           v
+-----------------------------------+
| OS 支援層                         |
|  - JobScheduler (API 23+)         |
|  - AlarmManager (API < 23)        |
|  - Battery / Power / Network Mgmt |
+-----------------------------------+

best practice

  • 首選 WorkManager
    • 若任務有持久性需求(例如同步、上傳、備份),建議直接使用 WorkManager。
  • 避免自建排程機制
    • 不要使用 Thread + Timer 或 Handler 自行排程,會與系統電源管理衝突。
  • 明確設定條件
    • 合理設定網路、電源條件,避免不必要的喚醒。
  • 觀察任務狀態
    • 善用 LiveData 或 Coroutine Flow 監控任務結果。
  • 版本兼容性
    • WorkManager 會自動向下兼容,省去大量 if/else 判斷。

summery

JobScheduler 是 Android Framework 的核心排程服務,能在滿足條件下統一安排背景任務,節能又可靠。
WorkManager 是 Jetpack 封裝層,提供跨版本、一致、可觀察的任務管理機制。
在 Android 現代開發中,WorkManager 幾乎可視為 「JobScheduler 的官方封裝版」。


上一篇
#19
下一篇
#21
系列文
安豬複習22
  1. 18
    #17
  2. 19
    #18
  3. 20
    #19
  4. 21
    #20
  5. 22
    #21
完整目錄
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言